#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<stdio.h>
#include<dirent.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<pwd.h>
#include<grp.h>
#include<getopt.h>

void print_type(mode_t st_mode){//类型
    if(S_ISDIR(st_mode)) //判断文件的类型
        printf("d"); //目录
    else if(S_ISBLK(st_mode)) //块文件
        printf("b");
    else if(S_ISCHR(st_mode)) //特殊字符文件
        printf("c");
    else if(S_ISREG(st_mode)) //普通文件
        printf("-");
    else if(S_ISLNK(st_mode)) //链接
        printf("l");
    else if(S_ISFIFO(st_mode)) //pipe
        printf("p");
    else if(S_ISSOCK(st_mode)) //pipe
        printf("s");
}
void print_perm(mode_t st_mode){//权限
    char perm[9];
    perm[0]=st_mode&S_IRUSR?'r':'-';
    perm[1]=st_mode&S_IWUSR?'w':'-';
    perm[2]=st_mode&S_IXUSR?'x':'-';
    perm[3]=st_mode&S_IRGRP?'r':'-';
    perm[4]=st_mode&S_IWGRP?'w':'-';
    perm[5]=st_mode&S_IXGRP?'x':'-';
    perm[6]=st_mode&S_IROTH?'r':'-';
    perm[7]=st_mode&S_IWOTH?'w':'-';
    perm[8]=st_mode&S_IXOTH?'x':'-';
    printf("%s\t", perm);
    // printf("%o\t",st_mode&0x1ff); //文件的权限
}
void print_link(nlink_t st_nlink){
    printf("%ld\t",st_nlink);
}
void print_usrname(uid_t st_uid){
    struct passwd* pwd;
    pwd = getpwuid(st_uid);
    printf("%s\t",pwd->pw_name);
}
void print_grname(gid_t st_gid){
    struct group *grp = getgrgid(getgid());
    printf("%s\t",grp->gr_name);
}
void print_time(struct timespec st_mtim){//最后修改时间
    char buf[32];
    char *p = NULL;
    strcpy(buf, (char*)ctime(&(st_mtim.tv_sec)));
    p = strchr(buf, '\n');
    *p = '\0';
    printf("%15s\t",buf);
}
void print_filename(char* filename){
    printf("%s\n",filename);
}
void print_stat(struct stat st){
    print_type(st.st_mode);
    print_perm(st.st_mode);
    print_link(st.st_nlink);
    print_usrname(st.st_uid);
    print_grname(st.st_gid);
    print_time(st.st_mtim);
    
    // printf("%15s\t",ctime_s(st.st_atime)); //文件创建时间
    // printf("%15s\t",ctime_s(st.st_mtime)); //文件上次修改时间
    // printf("%ld\n",st.st_size); //文件的大小
}
int main(int argc, char* argv[]){
    //TODO
    struct dirent *ep;
    struct stat st;
    char* dirpath = (char*)malloc(120);
    char* filepath = (char*)malloc(120);
    int showPrivate = 0;
    int showParent = 0;
    //解析命令行参数
	int opt;
	opterr =0 ;//不输出错误
	while ((opt = getopt (argc, argv, "-:a:b:")) != EOF){
   	 	switch (opt)
		{
			case 'a': 
                if(optarg!=NULL){
                    strcpy(dirpath,optarg);
                }
                showParent = 1;
				break;
			case 'b': 
                if(optarg!=NULL){
                    strcpy(dirpath,optarg);
                }
                showPrivate = 1;
				break;
			default:
				strcpy(dirpath,optarg);
                break;
		}
    }
    DIR* dp = opendir(dirpath);
    if(dp==NULL){
        printf("directory not exists.\n");
        return 0;
    }else{
        while(ep = readdir(dp)){
            sprintf(filepath,"%s/%s",dirpath,ep->d_name);
            if(stat(filepath,&st)==-1){
                printf("read failed.\n");
                return 0;
            }
            if(ep->d_name[0]=='.'){
                if(showPrivate!=0){
                    print_stat(st);
                    print_filename(ep->d_name);
                }else if(showParent!=0&&(strcmp(ep->d_name,".")==0||strcmp(ep->d_name,"..")==0)){
                    print_stat(st);
                    print_filename(ep->d_name);
                }
            }else{
                print_stat(st);
                print_filename(ep->d_name);
            }
        }
    }
    closedir(dp);
    return 0;
}